Introdução

Análise exploratória de dados do RottenTomatoes sobre o ator Jake Gyllenhaal. O código empregado na extração dos dados aqui analizados e a descrição de como o usar encontra-se no repositório origem deste relatório.

  • Entradas que não contêm dados sobre bilheteria foram ignoradas.




Data Overview

import_data("jake_gyllenhaal") 
filmes <- read_imported_data()
filmes %>% 
    glimpse()
Observations: 20
Variables: 5
$ avaliacao  <int> 92, 68, 73, 52, 73, 59, 82, 85, 92, 49, 35, 64, 47, 90, 87, 61, 62, 44, ...
$ filme      <chr> "Stronger", "Life", "Nocturnal Animals", "Demolition", "Everest", "South...
$ papel      <chr> "Jeff Bauman", "David Jordan", "Tony HastingsEdward Sheffield", "Davis M...
$ bilheteria <dbl> 4.2, 30.2, 10.7, 1.7, 46.6, 42.4, 61.0, 39.1, 54.7, 33.3, 90.8, 28.6, 9....
$ ano        <int> 2017, 2017, 2016, 2016, 2015, 2015, 2013, 2012, 2011, 2010, 2010, 2009, ...

Bilheteria

  • Dados de bilheteria se referem ao arrecadamento dentro dos Estados Unidos.
p <- filmes %>%
    ggplot(aes(x = ano, 
               y = bilheteria,
               text = paste("Filme:",filme,
                            "\nBilheteria:",
                            bilheteria,"m",
                            "\nAno:",ano))) + 
    geom_point(size = 4, color = paleta[1]) +
    labs(y = "Bilheteria", x = "Ano de lançamento")
ggplotly(p, tooltip = "text") %>%
    layout(autosize = F)
  • Entre os filmes em que Jake atuou um foge aos outros em termos de faturamento, o filme “The Day After Tomorrow” lançado em 2004.

  • É possível perceber uma tendência de queda no faturamento dos filmes em que Jake atuou após 2013.

filmes %>% 
    ggplot(aes(x = bilheteria)) + 
    geom_histogram(aes(y=(..count..)/sum(..count..)),binwidth = 10, boundary = 0, 
                   fill = "grey", color = "black") + 
    geom_rug(size = .5) +
    scale_x_continuous(breaks=seq(0,200,20)) +
    labs(y = "Frequência Relativa", x = "Bilheteria")

  • Vemos claramente a disparidade entre “The Day After Tomorrow” e os outros filmes.

  • Nenhum valor fora do domínio de valores esperado, e.g. valores negativos.

p <- filmes %>% 
    ggplot(aes(x = "",
               y = bilheteria,
               label = filme,
               text = paste("Filme:",filme,
                            "\nBilheteria:",
                            bilheteria,"m"))) + 
    geom_jitter(width = .05, alpha = .3, size = 3) + 
    labs(x = "", y="Bilheteria")
ggplotly(p, tooltip="text") %>% 
    layout(autosize = F)
  • Separar os filmes entre os de bilheteria abaixo e acima de 50 milhões parece uma abordagem razoável.

  • “The Day After Tomorrow” aparenta formar um exército de um filme só. O que nos daria 3 grupos.

Avaliação

p <- filmes %>% 
    ggplot(aes(x = ano, 
               y = avaliacao,
                text = paste("Filme:",filme,
                            "\nAvaliação:",
                            avaliacao,
                            "\nAno:",ano))) + 
    geom_point(size = 4, color = paleta[1])  +
    scale_y_continuous(limits = c(0, 100)) +
    labs(y = "Avaliação RT", x = "Ano de lançamento")
ggplotly(p, tooltip = "text") %>%
    layout(autosize = F)
  • Entre 2005 e 2010 Jake participou de uma série de filmes em particular que não agradou os críticos
  • Não aparenta haver uma tendência particularmente clara em razão do ano de lançamento.
filmes %>% 
    ggplot(aes(x = avaliacao)) + 
    geom_histogram(aes(y=(..count..)/sum(..count..)),binwidth = 10, boundary = 0, 
                   fill = paleta[3], color = "black") + 
    geom_rug(size = .5) +
    scale_x_continuous(breaks=seq(0,100,10)) +
    labs(y = "Frequência Relativa", x = "Avaliação RT")

  • É possível perceber uma quantidade considerável de filmes com notas acima de 80.

  • Nenhum valor fora do domínio de valores esperado, e.g. valores negativos.

p <- filmes %>% 
    ggplot(aes(x = "",
               y = avaliacao,
               text = paste(
                    "Filme:",filme,
                    "\nAvaliação:",avaliacao))) + 
    geom_jitter(width = .05, alpha = .3, size = 3) + 
    labs(x = "", y="Avaliação RT")
ggplotly(p, tooltip = "text") %>% 
    layout(autosize = F)
  • Intuitivamente três grupos surgem:
    • Os filmes com avaliação acima de 80
    • Os filmes com avaliação entre 55 e 70
    • Os filmes com avaliação abaixo de 55




Agrupamento hierárquico



Uma dimensão


Bilheteria

agrupamento_h = filmes %>% 
    mutate(nome = paste0(filme, " (bil=", bilheteria, ")")) %>% 
    as.data.frame() %>% 
    column_to_rownames("filme") %>% 
    select(bilheteria) %>%
    dist(method = "euclidian") %>% 
    hclust(method = "centroid")
ggdendrogram(agrupamento_h, rotate = T, size = 2, theme_dendro = F) +
    labs(y = "Dissimilaridade", x = "", title = "Dendrograma") +
    geom_hline(aes(yintercept = c(20,30), color=c("4 grupos","3 grupos"))) +
    scale_colour_manual(name="#Grupos",
    values=c("#56B4E9", "#FF9999"))

  • Em termos de Dendograma a divisão em quatro grupos assim como a divisão em 3 grupos parecem ser apropriadas, dado que o aumento de dissimilaridade de 4 para 3 grupos não aparentar ser substancial.
  • Corte feito para 4 grupos
atribuicoes = get_grupos(agrupamento_h, num_grupos = 1:6)
atribuicoes = atribuicoes %>% 
    left_join(filmes, by = c("label" = "filme"))
atribuicoes %>% 
    ggplot(aes(x = "Filmes", y = bilheteria, colour = grupo)) + 
    geom_jitter(width = .02, height = 0, size = 1.6, alpha = .6) + 
    facet_wrap(~ paste(k, " grupos")) + 
    scale_color_brewer(palette = "Dark2") +
    labs(y = "Bilheteria (milhões)", x = "", title = "Agrupamento por Bilheteria")

  • A divisão em 4 grupos parece ser mais apropriada que a divisão em 3 grupos.
    • O cluster de filmes na base do gráfico aparenta exigir um grupo próprio (Na divisão em 4 grupos o grupo mencionado seria o grupo 1).
k_escolhido = 4
m <- list(l = 220)
p <-atribuicoes %>% 
    filter(k == k_escolhido) %>% 
    ggplot(aes(x = reorder(label, bilheteria),
               y = bilheteria,
               colour = grupo,
               text = paste(
                    "Filme:", reorder(label, bilheteria),
                    "\nAvaliação:", bilheteria,
                    "\nGrupo:", grupo))) + 
    geom_jitter(width = .02, height = 0, size = 3, alpha = .6) + 
    facet_wrap(~ paste(k, " grupos")) + 
    scale_color_brewer(palette = "Dark2") + 
    labs(x = "", y = "Avaliação RT") + 
    coord_flip()
ggplotly(p,tooltip = "text") %>%
    layout(autosize = F, margin = m)
  • The Day After Tomorrow exigiu um grupo para si, como era esperado.


Avaliação

agrupamento_h = filmes %>% 
    mutate(nome = paste0(filme, " (av=", avaliacao, ")")) %>% 
    as.data.frame() %>% 
    column_to_rownames("filme") %>% 
    select(avaliacao) %>%
    dist(method = "euclidian") %>% 
    hclust(method = "ward.D")
ggdendrogram(agrupamento_h, rotate = T, size = 2, theme_dendro = F) +
    labs(y = "Dissimilaridade", x = "", title = "Dendrograma") +
    geom_hline(aes(yintercept = 30),color="red")

  • Em termos de Dendograma a divisão em três grupos parece ser a mais apropriada, dado que o aumento da dissimilaridade passa a ser substancial quando passamos de 3 para 2 grupos.
atribuicoes = get_grupos(agrupamento_h, num_grupos = 1:6)
atribuicoes = atribuicoes %>% 
    left_join(filmes, by = c("label" = "filme"))
atribuicoes %>% 
    ggplot(aes(x = "Filmes", y = avaliacao, colour = grupo)) + 
    geom_jitter(width = .02, height = 0, size = 1.6, alpha = .6) + 
    facet_wrap(~ paste(k, " grupos")) + 
    scale_color_brewer(palette = "Dark2") +
    labs(y = "Avaliação RT", x = "", title = "Agrupamento por Avaliação")

  • Visualmente a divisão em três grupos parece de fato ser apropriada, o que está em acordo com o dendrograma.
k_escolhido = 3
m <- list(l = 220)
p <-atribuicoes %>% 
    filter(k == k_escolhido) %>% 
    ggplot(aes(x = reorder(label, avaliacao),
               y = avaliacao,
               colour = grupo,
               text = paste(
                    "Filme:", reorder(label, avaliacao),
                    "\nAvaliação:", avaliacao,
                    "\nGrupo:", grupo))) + 
    geom_jitter(width = .02, height = 0, size = 3, alpha = .6) + 
    facet_wrap(~ paste(k, " grupos")) + 
    scale_color_brewer(palette = "Dark2") + 
    labs(x = "", y = "Avaliação RT") + 
    coord_flip()
ggplotly(p,tooltip = "text") %>%
    layout(autosize = F, margin = m)
  • Discutivelmente, Prince of Persia: The Sands of Time poderia exigir um grupo para si próprio.


Duas dimensões


Quantos grupos devemos escolher?


agrupamento_h_2d = filmes %>%
   mutate(bilheteria = log10(bilheteria)) %>%
   mutate_at(vars("avaliacao", "bilheteria"), funs(scale)) %>%
   column_to_rownames("filme") %>%
   select("avaliacao", "bilheteria") %>%
   dist(method = "euclidean") %>%
   hclust(method = "ward.D")
ggdendrogram(agrupamento_h_2d, rotate = TRUE, theme_dendro = F) +
    labs(y = "Dissimilaridade", x = "", title = "Dendrograma") +
    geom_hline(aes(yintercept = 4),color="red")

  • Passar de 4 para 3 grupos representa pouca variação em termos de dissimilaridade
  • Passar de 3 para 2 grupos apresenta um aumento relativo de dissimilaridade substancial, portanto de 6 até 3 grupos parece ser uma boa escolha em termos de dendrograma.
filmes2 <- filmes %>%
    mutate(bilheteria = log10(bilheteria))
plota_hclusts_2d(agrupamento_h_2d,
                filmes2,
                c("avaliacao", "bilheteria"),
                linkage_method = "ward.D", 
                ks = 1:6,
                palette = "Dark2") + 
    scale_y_log10() +
    labs(y = "Bilheteria", x = "Avaliação", title = "Agrupamento com Duas Dimensões")

  • A escolha por 5 grupos parece ser apropriada, por refletir tanto questões de bilheteria como de avaliação. Optaremos por 5 grupos pelas seguintes razões (Grupos mencionados no agrupamento de 5 grupos):
    • Os \(\color{magenta}{\text{4 filmes de melhores avaliações}}\) estão bem próximos uns dos outros e sugerem um grupo.
    • Os \(\color{#7C3F7C}{\text{3 filmes de baixas bilheterias e baixas avaliações}}\) estão bem distantes do resto dos filmes e sugerem um grupo.
    • Os \(\color{#16A085}{\text{4 filmes de baixa bilheteria e boas avaliações}}\) estão bem próximos uns dos outros e sugerem um grupo.
    • Os \(\color{green}{\text{2 filmes de altíssima bilheteria e baixíssima avaliação}}\) estão bem distantes do resto dos filmes e sugerem um grupo.
    • Os \(\color{#CF5300}{\text{6 filmes centrais/medianos em termos de bilheteria/avaliação}}\) estão bem próximos uns dos outros e sugerem um grupo.
atribuicoes = get_grupos(agrupamento_h_2d, num_grupos = 1:6)
atribuicoes = atribuicoes %>% 
    filter(k == 5) %>%
    mutate(filme = label) %>% 
    left_join(filmes, by = "filme")
p <- atribuicoes %>%
    ggplot(aes(x = avaliacao,
               y = bilheteria,
               colour = grupo,
               text = paste(
                    "Filme:", filme,
                    "\nBilheteria:", bilheteria,"m\n",
                    "Avaliação:", avaliacao))) + 
    geom_jitter(width = .02, height = 0, size = 3, alpha = .6) + 
    facet_wrap(~ paste(k, " grupos")) + 
    scale_color_brewer(palette = "Dark2") +
    scale_y_log10() +
    labs(y = "Bilheteria", x = "Avaliação RT")
ggplotly(p, tooltip = "text") %>%
    layout(autosize = F)




Quais os nomes dos grupos?


\(\color{#16A085}{\text{Grupo 1 (Oddball):}}\) Filmes em geral bem recebidos pela crítica porém mal recebidos pelo público, o que se reflete no seu baixo arrecadamento. O nome Oddball parte do interese de pessoas que se consideram excêntricas em buscarem filmes nesse perfil para revalidarem o sentimento de exclusividade.


\(\color{#CF5300}{\text{Grupo 2 (Sessão da Tarde):}}\) Filmes em geral não tão bem recebidos pela crítica e mais formulaicos. Em termos de bilheteria a maior parte deles foi baixa mas o filme se pagou.O nome Sessã da Tarde parte da ideia de que filmes mais formulaicos e inexpressivos em termos de bilheteria como os do grupo povoarem esse horário da tv brasileira.


\(\color{#7C3F7C}{\text{Grupo 3 (Demolition of a budget):}}\) Filmes em geral mal recebidos pela crítica e pelo público, o que se reflete no seu baixo arrecadamento e avaliações. O nome do grupo parte do baxissimo rendimento dos filmes em termos financeiros, a “demolição” do dinheiro investido na produção do filme.


\(\color{magenta}{\text{Grupo 4 (Broke Records and Awards):}}\) Filmes aclamados pela crítica e de faturamento decente ou de sucesso, os filmes desse grupo são de tom mais sério tratando de assuntos significativos e geradores de controvérsia (assassinatos em série verídicos, não heterossexualidade, terrorismo.. ). O nome do grupo é um trocadilho com o nome de um dos filmes e a quantidade exorbitante de prêmios que esse filme ganhou.


\(\color{green}{\text{Grupo 5 (BlockBusters):}}\) Filmes em que Jack atuou que os críticos não gostaram lá muito mas que excederam em bilheteria, com uma arrecadação girando na casa da centena de milhões de dólares. O termo BlockBuster é usualmente dado a filmes que lotam as salas de cinema, que é o caso dos filmes pertencentes a esse grupo.




Filme-exemplo de cada grupo


\(\color{#16A085}{\text{Grupo 1 (Oddball):}}\)

  • Stronger: Filme biográfico sobre ‘Jeff Bauman’, vítima do atentado de Boston que perdeu ambas as pernas na explosão. O filme foi muito bem recebido pelos críticos que o elogiaram por ser bem executado, comovente e por focar numa história de superação ao invés de usar a tragédia para alimentar a paranóia em cima do terrorismo. O filme porém foi um fracasso em termos de bilheteria.


\(\color{#CF5300}{\text{Grupo 2 (Sessão da Tarde):}}\)

  • Life: Filme no gênero ficção científica espacial, teve um arrecadamento não muito expressivo assim como críticas igualmente pouco entusiasmadas. Foi considerado por muitos bem executados porém pouco inovativo.


\(\color{#7C3F7C}{\text{Grupo 3 (Demolition of a budget):}}\)

  • Demolition: Neste filme Jake atua no papel de um homem que volta ao trabalho depois de perder a esposa e encontra contato humano em uma atendente de telemarketing ao reclamar de uma vending machine. O filme foi um fracasso em termos de arrecadamento assim como em termos de crítica. O filme teve seu script apontado como grande problema, esse foi descrito como ‘tentando afetar profundidade’ e anti-carismático.


\(\color{magenta}{\text{Grupo 4 (Broke Records and Awards):}}\)

  • Brokeback Mountain: Provavelmente a melhor atuação de Jake Gyllenhaal até o momento, esse filme rendeu a Jake uma indicação ao Oscar e levantou muita controvérsia por conter uma cena de sexo entre pessoas do mesmo sexo. A Academia (responsável por escolher os vencedores do Oscar) foi acusada de homofobia por não escolher esse filme como o ganhador de Melhor Fotografia, ainda assim Brokeback Mountain ganhou outros 141 prêmios e 128 nominações de acordo com o IMDB. O filme foi considerado um sucesso tanto em faturamento como em avaliação.


\(\color{green}{\text{Grupo 5 (BlockBusters):}}\)

  • Prince of Persia: The Sands of Time: Baseado no jogo de mesmo nome, jogo que ainda é pra muitos uma referência em qualidade e inovação. O filme resultou em comentários decepcionados tanto de críticos e fãs, os quais curiosamente não falharam em contribuir pro arrecadamento do filme.
LS0tCnRpdGxlOiAiVGlwb3MgZGUgZmlsbWUgZGUgSmFrZSBHeWxsZW5oYWFsIgphdXRob3I6ICJKb3PDqSBCZW5hcmRpIGRlIFNvdXphIE51bmVzIgpkYXRlOiAiMjIvMDUvMjAxOCIKb3V0cHV0OgogIGh0bWxfZG9jdW1lbnQ6CiAgICBkZl9wcmludDogcGFnZWQKICAgIHRvYzogeWVzCiAgICB0b2NfZmxvYXQ6IHllcwogIGh0bWxfbm90ZWJvb2s6CiAgICB0b2M6IHllcwogICAgdG9jX2Zsb2F0OiB5ZXMKLS0tCgo8YnIvPjxici8+CgojIEludHJvZHXDp8OjbwoKPiBBbsOhbGlzZSBleHBsb3JhdMOzcmlhIGRlIGRhZG9zIGRvIFtSb3R0ZW5Ub21hdG9lc10oaHR0cHM6Ly93d3cucm90dGVudG9tYXRvZXMuY29tLykgc29icmUgbyBhdG9yIEpha2UgR3lsbGVuaGFhbC4gTyBjw7NkaWdvIGVtcHJlZ2FkbyBuYSBleHRyYcOnw6NvIGRvcyBkYWRvcyBhcXVpIGFuYWxpemFkb3MgZSBhIGRlc2NyacOnw6NvIGRlIGNvbW8gbyB1c2FyIGVuY29udHJhLXNlIG5vICBbcmVwb3NpdMOzcmlvIG9yaWdlbV0oaHR0cHM6Ly9naXRodWIuY29tL0JlbmFyZGkvYWdydXBhbWVudG8tZmlsbWVzLykgZGVzdGUgcmVsYXTDs3Jpby4KCiogRW50cmFkYXMgcXVlIG7Do28gY29udMOqbSBkYWRvcyBzb2JyZSBiaWxoZXRlcmlhIGZvcmFtIGlnbm9yYWRhcy4KCjxicj4KCioqKgoKPGJyPgoKYGBge3IgZWNobz1GQUxTRSwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KbGlicmFyeSh0aWR5dmVyc2UpCmxpYnJhcnkoaGVyZSkKbGlicmFyeShjbHVzdGVyKQpsaWJyYXJ5KHBsb3RseSkKbGlicmFyeShnZ2RlbmRybykKCnNvdXJjZShoZXJlOjpoZXJlKCJjb2RlL2xpYi5SIikpCnNvdXJjZShoZXJlOjpoZXJlKCJjb2RlL3Bsb3RhX3NvbHVjb2VzX2hjbHVzdC5SIikpCgp0aGVtZV9zZXQodGhlbWVfcmVwb3J0KCkpCgprbml0cjo6b3B0c19jaHVuayRzZXQodGlkeSA9IEZBTFNFLAogICAgICAgICAgICAgICAgICAgICAgZmlnLndpZHRoID0gNiwKICAgICAgICAgICAgICAgICAgICAgIGZpZy5oZWlnaHQgPSA1LAogICAgICAgICAgICAgICAgICAgICAgZWNobyA9IFRSVUUpCnBhbGV0YSA9IGMoIiM0MDRFNEQiLAogICAgICAgICAgICIjOTJEQ0U1IiwKICAgICAgICAgICAiIzkzOEJBMSIsCiAgICAgICAgICAgIiMyRDMxNDIiLAogICAgICAgICAgICIjRjQ3NDNCIikKYGBgCgojIERhdGEgT3ZlcnZpZXcKCmBgYHtyIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CmltcG9ydF9kYXRhKCJqYWtlX2d5bGxlbmhhYWwiKSAKZmlsbWVzIDwtIHJlYWRfaW1wb3J0ZWRfZGF0YSgpCmZpbG1lcyAlPiUgCiAgICBnbGltcHNlKCkKYGBgCgojIyBCaWxoZXRlcmlhCgoqIERhZG9zIGRlIGJpbGhldGVyaWEgc2UgcmVmZXJlbSBhbyBhcnJlY2FkYW1lbnRvIGRlbnRybyBkb3MgRXN0YWRvcyBVbmlkb3MuCgpgYGB7cn0KcCA8LSBmaWxtZXMgJT4lCiAgICBnZ3Bsb3QoYWVzKHggPSBhbm8sIAogICAgICAgICAgICAgICB5ID0gYmlsaGV0ZXJpYSwKICAgICAgICAgICAgICAgdGV4dCA9IHBhc3RlKCJGaWxtZToiLGZpbG1lLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIlxuQmlsaGV0ZXJpYToiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgYmlsaGV0ZXJpYSwibSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAiXG5Bbm86Iixhbm8pKSkgKyAKICAgIGdlb21fcG9pbnQoc2l6ZSA9IDQsIGNvbG9yID0gcGFsZXRhWzFdKSArCiAgICBsYWJzKHkgPSAiQmlsaGV0ZXJpYSIsIHggPSAiQW5vIGRlIGxhbsOnYW1lbnRvIikKCmdncGxvdGx5KHAsIHRvb2x0aXAgPSAidGV4dCIpICU+JQogICAgbGF5b3V0KGF1dG9zaXplID0gRikKYGBgCgoqIEVudHJlIG9zIGZpbG1lcyBlbSBxdWUgSmFrZSBhdHVvdSB1bSBmb2dlIGFvcyBvdXRyb3MgZW0gdGVybW9zIGRlIGZhdHVyYW1lbnRvLCBvIGZpbG1lICAqKiJUaGUgRGF5IEFmdGVyIFRvbW9ycm93IioqIGxhbsOnYWRvIGVtIDIwMDQuCgoqIMOJIHBvc3PDrXZlbCBwZXJjZWJlciB1bWEgdGVuZMOqbmNpYSBkZSBxdWVkYSBubyBmYXR1cmFtZW50byBkb3MgZmlsbWVzIGVtIHF1ZSBKYWtlIGF0dW91IGFww7NzIDIwMTMuCgpgYGB7cn0KZmlsbWVzICU+JSAKICAgIGdncGxvdChhZXMoeCA9IGJpbGhldGVyaWEpKSArIAogICAgZ2VvbV9oaXN0b2dyYW0oYWVzKHk9KC4uY291bnQuLikvc3VtKC4uY291bnQuLikpLGJpbndpZHRoID0gMTAsIGJvdW5kYXJ5ID0gMCwgCiAgICAgICAgICAgICAgICAgICBmaWxsID0gImdyZXkiLCBjb2xvciA9ICJibGFjayIpICsgCiAgICBnZW9tX3J1ZyhzaXplID0gLjUpICsKICAgIHNjYWxlX3hfY29udGludW91cyhicmVha3M9c2VxKDAsMjAwLDIwKSkgKwogICAgbGFicyh5ID0gIkZyZXF1w6puY2lhIFJlbGF0aXZhIiwgeCA9ICJCaWxoZXRlcmlhIikKCmBgYAoKKiBWZW1vcyBjbGFyYW1lbnRlIGEgZGlzcGFyaWRhZGUgZW50cmUgKioiVGhlIERheSBBZnRlciBUb21vcnJvdyIqKiAgZSBvcyBvdXRyb3MgZmlsbWVzLgoKKiBOZW5odW0gdmFsb3IgZm9yYSBkbyBkb23DrW5pbyBkZSB2YWxvcmVzIGVzcGVyYWRvLCBlLmcuIHZhbG9yZXMgbmVnYXRpdm9zLgoKYGBge3J9CnAgPC0gZmlsbWVzICU+JSAKICAgIGdncGxvdChhZXMoeCA9ICIiLAogICAgICAgICAgICAgICB5ID0gYmlsaGV0ZXJpYSwKICAgICAgICAgICAgICAgbGFiZWwgPSBmaWxtZSwKICAgICAgICAgICAgICAgdGV4dCA9IHBhc3RlKCJGaWxtZToiLGZpbG1lLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIlxuQmlsaGV0ZXJpYToiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgYmlsaGV0ZXJpYSwibSIpKSkgKyAKICAgIGdlb21faml0dGVyKHdpZHRoID0gLjA1LCBhbHBoYSA9IC4zLCBzaXplID0gMykgKyAKICAgIGxhYnMoeCA9ICIiLCB5PSJCaWxoZXRlcmlhIikKCmdncGxvdGx5KHAsIHRvb2x0aXA9InRleHQiKSAlPiUgCiAgICBsYXlvdXQoYXV0b3NpemUgPSBGKQpgYGAKCiogU2VwYXJhciBvcyBmaWxtZXMgZW50cmUgb3MgZGUgYmlsaGV0ZXJpYSBhYmFpeG8gZSBhY2ltYSBkZSA1MCBtaWxow7VlcyBwYXJlY2UgdW1hIGFib3JkYWdlbSByYXpvw6F2ZWwuCgoqICoqIlRoZSBEYXkgQWZ0ZXIgVG9tb3Jyb3ciKiogYXBhcmVudGEgZm9ybWFyIHVtIGV4w6lyY2l0byBkZSB1bSBmaWxtZSBzw7MuIE8gcXVlIG5vcyBkYXJpYSAzIGdydXBvcy4gCgojIyBBdmFsaWHDp8OjbwoKYGBge3J9CnAgPC0gZmlsbWVzICU+JSAKICAgIGdncGxvdChhZXMoeCA9IGFubywgCiAgICAgICAgICAgICAgIHkgPSBhdmFsaWFjYW8sCiAgICAgICAgICAgICAgICB0ZXh0ID0gcGFzdGUoIkZpbG1lOiIsZmlsbWUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAiXG5BdmFsaWHDp8OjbzoiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgYXZhbGlhY2FvLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIlxuQW5vOiIsYW5vKSkpICsgCiAgICBnZW9tX3BvaW50KHNpemUgPSA0LCBjb2xvciA9IHBhbGV0YVsxXSkgICsKICAgIHNjYWxlX3lfY29udGludW91cyhsaW1pdHMgPSBjKDAsIDEwMCkpICsKICAgIGxhYnMoeSA9ICJBdmFsaWHDp8OjbyBSVCIsIHggPSAiQW5vIGRlIGxhbsOnYW1lbnRvIikKCmdncGxvdGx5KHAsIHRvb2x0aXAgPSAidGV4dCIpICU+JQogICAgbGF5b3V0KGF1dG9zaXplID0gRikKYGBgCgoqIEVudHJlIDIwMDUgZSAyMDEwIEpha2UgcGFydGljaXBvdSBkZSB1bWEgc8OpcmllIGRlIGZpbG1lcyBlbSBwYXJ0aWN1bGFyIHF1ZSBuw6NvIGFncmFkb3Ugb3MgY3LDrXRpY29zIAoqIE7Do28gYXBhcmVudGEgaGF2ZXIgdW1hIHRlbmTDqm5jaWEgcGFydGljdWxhcm1lbnRlIGNsYXJhIGVtIHJhesOjbyBkbyBhbm8gZGUgbGFuw6dhbWVudG8uIAoKYGBge3J9CmZpbG1lcyAlPiUgCiAgICBnZ3Bsb3QoYWVzKHggPSBhdmFsaWFjYW8pKSArIAogICAgZ2VvbV9oaXN0b2dyYW0oYWVzKHk9KC4uY291bnQuLikvc3VtKC4uY291bnQuLikpLGJpbndpZHRoID0gMTAsIGJvdW5kYXJ5ID0gMCwgCiAgICAgICAgICAgICAgICAgICBmaWxsID0gcGFsZXRhWzNdLCBjb2xvciA9ICJibGFjayIpICsgCiAgICBnZW9tX3J1ZyhzaXplID0gLjUpICsKICAgIHNjYWxlX3hfY29udGludW91cyhicmVha3M9c2VxKDAsMTAwLDEwKSkgKwogICAgbGFicyh5ID0gIkZyZXF1w6puY2lhIFJlbGF0aXZhIiwgeCA9ICJBdmFsaWHDp8OjbyBSVCIpCgpgYGAKCiogw4kgcG9zc8OtdmVsIHBlcmNlYmVyIHVtYSBxdWFudGlkYWRlIGNvbnNpZGVyw6F2ZWwgZGUgZmlsbWVzIGNvbSBub3RhcyBhY2ltYSBkZSA4MC4KCiogTmVuaHVtIHZhbG9yIGZvcmEgZG8gZG9tw61uaW8gZGUgdmFsb3JlcyBlc3BlcmFkbywgZS5nLiB2YWxvcmVzIG5lZ2F0aXZvcy4KCgpgYGB7cn0KcCA8LSBmaWxtZXMgJT4lIAogICAgZ2dwbG90KGFlcyh4ID0gIiIsCiAgICAgICAgICAgICAgIHkgPSBhdmFsaWFjYW8sCiAgICAgICAgICAgICAgIHRleHQgPSBwYXN0ZSgKICAgICAgICAgICAgICAgICAgICAiRmlsbWU6IixmaWxtZSwKICAgICAgICAgICAgICAgICAgICAiXG5BdmFsaWHDp8OjbzoiLGF2YWxpYWNhbykpKSArIAogICAgZ2VvbV9qaXR0ZXIod2lkdGggPSAuMDUsIGFscGhhID0gLjMsIHNpemUgPSAzKSArIAogICAgbGFicyh4ID0gIiIsIHk9IkF2YWxpYcOnw6NvIFJUIikKCmdncGxvdGx5KHAsIHRvb2x0aXAgPSAidGV4dCIpICU+JSAKICAgIGxheW91dChhdXRvc2l6ZSA9IEYpCgpgYGAKCiogSW50dWl0aXZhbWVudGUgdHLDqnMgZ3J1cG9zIHN1cmdlbToKICAgICogT3MgZmlsbWVzIGNvbSBhdmFsaWHDp8OjbyBhY2ltYSBkZSA4MAogICAgKiBPcyBmaWxtZXMgY29tIGF2YWxpYcOnw6NvIGVudHJlIDU1IGUgNzAgCiAgICAqIE9zIGZpbG1lcyBjb20gYXZhbGlhw6fDo28gYWJhaXhvIGRlIDU1Cgo8YnI+CgoqKioKCjxicj4KCiMgQWdydXBhbWVudG8gaGllcsOhcnF1aWNvCgo8YnI+Cjxicj4KCiMjIFVtYSBkaW1lbnPDo28KCjxicj4KCiMjIyBCaWxoZXRlcmlhIAoKYGBge3J9CmFncnVwYW1lbnRvX2ggPSBmaWxtZXMgJT4lIAogICAgbXV0YXRlKG5vbWUgPSBwYXN0ZTAoZmlsbWUsICIgKGJpbD0iLCBiaWxoZXRlcmlhLCAiKSIpKSAlPiUgCiAgICBhcy5kYXRhLmZyYW1lKCkgJT4lIAogICAgY29sdW1uX3RvX3Jvd25hbWVzKCJmaWxtZSIpICU+JSAKICAgIHNlbGVjdChiaWxoZXRlcmlhKSAlPiUKICAgIGRpc3QobWV0aG9kID0gImV1Y2xpZGlhbiIpICU+JSAKICAgIGhjbHVzdChtZXRob2QgPSAiY2VudHJvaWQiKQoKZ2dkZW5kcm9ncmFtKGFncnVwYW1lbnRvX2gsIHJvdGF0ZSA9IFQsIHNpemUgPSAyLCB0aGVtZV9kZW5kcm8gPSBGKSArCiAgICBsYWJzKHkgPSAiRGlzc2ltaWxhcmlkYWRlIiwgeCA9ICIiLCB0aXRsZSA9ICJEZW5kcm9ncmFtYSIpICsKICAgIGdlb21faGxpbmUoYWVzKHlpbnRlcmNlcHQgPSBjKDIwLDMwKSwgY29sb3I9YygiNCBncnVwb3MiLCIzIGdydXBvcyIpKSkgKwogICAgc2NhbGVfY29sb3VyX21hbnVhbChuYW1lPSIjR3J1cG9zIiwKICAgIHZhbHVlcz1jKCIjNTZCNEU5IiwgIiNGRjk5OTkiKSkKYGBgCgoqIEVtIHRlcm1vcyBkZSBEZW5kb2dyYW1hIGEgZGl2aXPDo28gZW0gcXVhdHJvIGdydXBvcyBhc3NpbSBjb21vIGEgZGl2aXPDo28gZW0gMyBncnVwb3MgcGFyZWNlbSBzZXIgYXByb3ByaWFkYXMsIGRhZG8gcXVlIG8gYXVtZW50byBkZSBkaXNzaW1pbGFyaWRhZGUgZGUgNCBwYXJhIDMgZ3J1cG9zIG7Do28gYXBhcmVudGFyIHNlciBzdWJzdGFuY2lhbC4KKiAgQ29ydGUgZmVpdG8gcGFyYSA0IGdydXBvcwoKYGBge3J9CmF0cmlidWljb2VzID0gZ2V0X2dydXBvcyhhZ3J1cGFtZW50b19oLCBudW1fZ3J1cG9zID0gMTo2KQoKYXRyaWJ1aWNvZXMgPSBhdHJpYnVpY29lcyAlPiUgCiAgICBsZWZ0X2pvaW4oZmlsbWVzLCBieSA9IGMoImxhYmVsIiA9ICJmaWxtZSIpKQoKYXRyaWJ1aWNvZXMgJT4lIAogICAgZ2dwbG90KGFlcyh4ID0gIkZpbG1lcyIsIHkgPSBiaWxoZXRlcmlhLCBjb2xvdXIgPSBncnVwbykpICsgCiAgICBnZW9tX2ppdHRlcih3aWR0aCA9IC4wMiwgaGVpZ2h0ID0gMCwgc2l6ZSA9IDEuNiwgYWxwaGEgPSAuNikgKyAKICAgIGZhY2V0X3dyYXAofiBwYXN0ZShrLCAiIGdydXBvcyIpKSArIAogICAgc2NhbGVfY29sb3JfYnJld2VyKHBhbGV0dGUgPSAiRGFyazIiKSArCiAgICBsYWJzKHkgPSAiQmlsaGV0ZXJpYSAobWlsaMO1ZXMpIiwgeCA9ICIiLCB0aXRsZSA9ICJBZ3J1cGFtZW50byBwb3IgQmlsaGV0ZXJpYSIpCgpgYGAKCiogQSBkaXZpc8OjbyBlbSA0IGdydXBvcyBwYXJlY2Ugc2VyIG1haXMgYXByb3ByaWFkYSBxdWUgYSBkaXZpc8OjbyBlbSAzIGdydXBvcy4KICAgICogTyBjbHVzdGVyIGRlIGZpbG1lcyBuYSBiYXNlIGRvIGdyw6FmaWNvIGFwYXJlbnRhIGV4aWdpciB1bSBncnVwbyBwcsOzcHJpbyAoTmEgZGl2aXPDo28gZW0gNCBncnVwb3MgbyBncnVwbyBtZW5jaW9uYWRvIHNlcmlhIG8gZ3J1cG8gMSkuIAoKYGBge3J9CmtfZXNjb2xoaWRvID0gNAoKbSA8LSBsaXN0KGwgPSAyMjApCgpwIDwtYXRyaWJ1aWNvZXMgJT4lIAogICAgZmlsdGVyKGsgPT0ga19lc2NvbGhpZG8pICU+JSAKICAgIGdncGxvdChhZXMoeCA9IHJlb3JkZXIobGFiZWwsIGJpbGhldGVyaWEpLAogICAgICAgICAgICAgICB5ID0gYmlsaGV0ZXJpYSwKICAgICAgICAgICAgICAgY29sb3VyID0gZ3J1cG8sCiAgICAgICAgICAgICAgIHRleHQgPSBwYXN0ZSgKICAgICAgICAgICAgICAgICAgICAiRmlsbWU6IiwgcmVvcmRlcihsYWJlbCwgYmlsaGV0ZXJpYSksCiAgICAgICAgICAgICAgICAgICAgIlxuQXZhbGlhw6fDo286IiwgYmlsaGV0ZXJpYSwKICAgICAgICAgICAgICAgICAgICAiXG5HcnVwbzoiLCBncnVwbykpKSArIAogICAgZ2VvbV9qaXR0ZXIod2lkdGggPSAuMDIsIGhlaWdodCA9IDAsIHNpemUgPSAzLCBhbHBoYSA9IC42KSArIAogICAgZmFjZXRfd3JhcCh+IHBhc3RlKGssICIgZ3J1cG9zIikpICsgCiAgICBzY2FsZV9jb2xvcl9icmV3ZXIocGFsZXR0ZSA9ICJEYXJrMiIpICsgCiAgICBsYWJzKHggPSAiIiwgeSA9ICJBdmFsaWHDp8OjbyBSVCIpICsgCiAgICBjb29yZF9mbGlwKCkKCmdncGxvdGx5KHAsdG9vbHRpcCA9ICJ0ZXh0IikgJT4lCiAgICBsYXlvdXQoYXV0b3NpemUgPSBGLCBtYXJnaW4gPSBtKQoKYGBgCgoqICoqVGhlIERheSBBZnRlciBUb21vcnJvdyoqIGV4aWdpdSB1bSBncnVwbyBwYXJhIHNpLCBjb21vIGVyYSBlc3BlcmFkby4KCjxicj4KCiMjIyBBdmFsaWHDp8OjbyAKCmBgYHtyfQphZ3J1cGFtZW50b19oID0gZmlsbWVzICU+JSAKICAgIG11dGF0ZShub21lID0gcGFzdGUwKGZpbG1lLCAiIChhdj0iLCBhdmFsaWFjYW8sICIpIikpICU+JSAKICAgIGFzLmRhdGEuZnJhbWUoKSAlPiUgCiAgICBjb2x1bW5fdG9fcm93bmFtZXMoImZpbG1lIikgJT4lIAogICAgc2VsZWN0KGF2YWxpYWNhbykgJT4lCiAgICBkaXN0KG1ldGhvZCA9ICJldWNsaWRpYW4iKSAlPiUgCiAgICBoY2x1c3QobWV0aG9kID0gIndhcmQuRCIpCgpnZ2RlbmRyb2dyYW0oYWdydXBhbWVudG9faCwgcm90YXRlID0gVCwgc2l6ZSA9IDIsIHRoZW1lX2RlbmRybyA9IEYpICsKICAgIGxhYnMoeSA9ICJEaXNzaW1pbGFyaWRhZGUiLCB4ID0gIiIsIHRpdGxlID0gIkRlbmRyb2dyYW1hIikgKwogICAgZ2VvbV9obGluZShhZXMoeWludGVyY2VwdCA9IDMwKSxjb2xvcj0icmVkIikKYGBgCgoqIEVtIHRlcm1vcyBkZSBEZW5kb2dyYW1hIGEgKipkaXZpc8OjbyBlbSB0csOqcyBncnVwb3MgcGFyZWNlIHNlciBhIG1haXMgYXByb3ByaWFkYSoqLCBkYWRvIHF1ZSBvIGF1bWVudG8gZGEgZGlzc2ltaWxhcmlkYWRlIHBhc3NhIGEgc2VyIHN1YnN0YW5jaWFsIHF1YW5kbyBwYXNzYW1vcyBkZSAzIHBhcmEgMiBncnVwb3MuCgpgYGB7cn0KYXRyaWJ1aWNvZXMgPSBnZXRfZ3J1cG9zKGFncnVwYW1lbnRvX2gsIG51bV9ncnVwb3MgPSAxOjYpCgphdHJpYnVpY29lcyA9IGF0cmlidWljb2VzICU+JSAKICAgIGxlZnRfam9pbihmaWxtZXMsIGJ5ID0gYygibGFiZWwiID0gImZpbG1lIikpCgphdHJpYnVpY29lcyAlPiUgCiAgICBnZ3Bsb3QoYWVzKHggPSAiRmlsbWVzIiwgeSA9IGF2YWxpYWNhbywgY29sb3VyID0gZ3J1cG8pKSArIAogICAgZ2VvbV9qaXR0ZXIod2lkdGggPSAuMDIsIGhlaWdodCA9IDAsIHNpemUgPSAxLjYsIGFscGhhID0gLjYpICsgCiAgICBmYWNldF93cmFwKH4gcGFzdGUoaywgIiBncnVwb3MiKSkgKyAKICAgIHNjYWxlX2NvbG9yX2JyZXdlcihwYWxldHRlID0gIkRhcmsyIikgKwogICAgbGFicyh5ID0gIkF2YWxpYcOnw6NvIFJUIiwgeCA9ICIiLCB0aXRsZSA9ICJBZ3J1cGFtZW50byBwb3IgQXZhbGlhw6fDo28iKQoKYGBgCgoqIFZpc3VhbG1lbnRlIGEgZGl2aXPDo28gZW0gdHLDqnMgZ3J1cG9zIHBhcmVjZSBkZSBmYXRvIHNlciBhcHJvcHJpYWRhLCBvIHF1ZSBlc3TDoSBlbSBhY29yZG8gY29tIG8gZGVuZHJvZ3JhbWEuCgpgYGB7cn0Ka19lc2NvbGhpZG8gPSAzCgptIDwtIGxpc3QobCA9IDIyMCkKCnAgPC1hdHJpYnVpY29lcyAlPiUgCiAgICBmaWx0ZXIoayA9PSBrX2VzY29saGlkbykgJT4lIAogICAgZ2dwbG90KGFlcyh4ID0gcmVvcmRlcihsYWJlbCwgYXZhbGlhY2FvKSwKICAgICAgICAgICAgICAgeSA9IGF2YWxpYWNhbywKICAgICAgICAgICAgICAgY29sb3VyID0gZ3J1cG8sCiAgICAgICAgICAgICAgIHRleHQgPSBwYXN0ZSgKICAgICAgICAgICAgICAgICAgICAiRmlsbWU6IiwgcmVvcmRlcihsYWJlbCwgYXZhbGlhY2FvKSwKICAgICAgICAgICAgICAgICAgICAiXG5BdmFsaWHDp8OjbzoiLCBhdmFsaWFjYW8sCiAgICAgICAgICAgICAgICAgICAgIlxuR3J1cG86IiwgZ3J1cG8pKSkgKyAKICAgIGdlb21faml0dGVyKHdpZHRoID0gLjAyLCBoZWlnaHQgPSAwLCBzaXplID0gMywgYWxwaGEgPSAuNikgKyAKICAgIGZhY2V0X3dyYXAofiBwYXN0ZShrLCAiIGdydXBvcyIpKSArIAogICAgc2NhbGVfY29sb3JfYnJld2VyKHBhbGV0dGUgPSAiRGFyazIiKSArIAogICAgbGFicyh4ID0gIiIsIHkgPSAiQXZhbGlhw6fDo28gUlQiKSArIAogICAgY29vcmRfZmxpcCgpCgpnZ3Bsb3RseShwLHRvb2x0aXAgPSAidGV4dCIpICU+JQogICAgbGF5b3V0KGF1dG9zaXplID0gRiwgbWFyZ2luID0gbSkKCmBgYAoKKiBEaXNjdXRpdmVsbWVudGUsICoqUHJpbmNlIG9mIFBlcnNpYTogVGhlIFNhbmRzIG9mIFRpbWUqKiBwb2RlcmlhIGV4aWdpciB1bSBncnVwbyBwYXJhIHNpIHByw7NwcmlvLgoKPGJyPgoKIyMgRHVhcyBkaW1lbnPDtWVzCgo8YnI+CgojIyMgUXVhbnRvcyBncnVwb3MgZGV2ZW1vcyBlc2NvbGhlcj8gCgo8YnI+CgpgYGB7ciwgd2FybmluZz1GQUxTRX0KYWdydXBhbWVudG9faF8yZCA9IGZpbG1lcyAlPiUKICAgbXV0YXRlKGJpbGhldGVyaWEgPSBsb2cxMChiaWxoZXRlcmlhKSkgJT4lCiAgIG11dGF0ZV9hdCh2YXJzKCJhdmFsaWFjYW8iLCAiYmlsaGV0ZXJpYSIpLCBmdW5zKHNjYWxlKSkgJT4lCiAgIGNvbHVtbl90b19yb3duYW1lcygiZmlsbWUiKSAlPiUKICAgc2VsZWN0KCJhdmFsaWFjYW8iLCAiYmlsaGV0ZXJpYSIpICU+JQogICBkaXN0KG1ldGhvZCA9ICJldWNsaWRlYW4iKSAlPiUKICAgaGNsdXN0KG1ldGhvZCA9ICJ3YXJkLkQiKQoKZ2dkZW5kcm9ncmFtKGFncnVwYW1lbnRvX2hfMmQsIHJvdGF0ZSA9IFRSVUUsIHRoZW1lX2RlbmRybyA9IEYpICsKICAgIGxhYnMoeSA9ICJEaXNzaW1pbGFyaWRhZGUiLCB4ID0gIiIsIHRpdGxlID0gIkRlbmRyb2dyYW1hIikgKwogICAgZ2VvbV9obGluZShhZXMoeWludGVyY2VwdCA9IDQpLGNvbG9yPSJyZWQiKQoKYGBgCgoqIFBhc3NhciBkZSA0IHBhcmEgMyBncnVwb3MgcmVwcmVzZW50YSBwb3VjYSB2YXJpYcOnw6NvIGVtIHRlcm1vcyBkZSBkaXNzaW1pbGFyaWRhZGUKKiBQYXNzYXIgZGUgMyBwYXJhIDIgZ3J1cG9zIGFwcmVzZW50YSB1bSBhdW1lbnRvIHJlbGF0aXZvIGRlIGRpc3NpbWlsYXJpZGFkZSBzdWJzdGFuY2lhbCwgcG9ydGFudG8gZGUgNiBhdMOpIDMgZ3J1cG9zIHBhcmVjZSBzZXIgdW1hIGJvYSBlc2NvbGhhIGVtIHRlcm1vcyBkZSBkZW5kcm9ncmFtYS4KCmBgYHtyfQpmaWxtZXMyIDwtIGZpbG1lcyAlPiUKICAgIG11dGF0ZShiaWxoZXRlcmlhID0gbG9nMTAoYmlsaGV0ZXJpYSkpCgpwbG90YV9oY2x1c3RzXzJkKGFncnVwYW1lbnRvX2hfMmQsCiAgICAgICAgICAgICAgICBmaWxtZXMyLAogICAgICAgICAgICAgICAgYygiYXZhbGlhY2FvIiwgImJpbGhldGVyaWEiKSwKICAgICAgICAgICAgICAgIGxpbmthZ2VfbWV0aG9kID0gIndhcmQuRCIsIAogICAgICAgICAgICAgICAga3MgPSAxOjYsCiAgICAgICAgICAgICAgICBwYWxldHRlID0gIkRhcmsyIikgKyAKICAgIHNjYWxlX3lfbG9nMTAoKSArCiAgICBsYWJzKHkgPSAiQmlsaGV0ZXJpYSIsIHggPSAiQXZhbGlhw6fDo28iLCB0aXRsZSA9ICJBZ3J1cGFtZW50byBjb20gRHVhcyBEaW1lbnPDtWVzIikKYGBgCgoqIEEgZXNjb2xoYSBwb3IgNSBncnVwb3MgcGFyZWNlIHNlciBhcHJvcHJpYWRhLCBwb3IgcmVmbGV0aXIgdGFudG8gcXVlc3TDtWVzIGRlIGJpbGhldGVyaWEgY29tbyBkZSBhdmFsaWHDp8Ojby4gKipPcHRhcmVtb3MgcG9yIDUgZ3J1cG9zKiogcGVsYXMgc2VndWludGVzIHJhesO1ZXMgKEdydXBvcyBtZW5jaW9uYWRvcyBubyBhZ3J1cGFtZW50byBkZSA1IGdydXBvcyk6IAogICAgKiBPcyAkXGNvbG9ye21hZ2VudGF9e1x0ZXh0ezQgZmlsbWVzIGRlIG1lbGhvcmVzIGF2YWxpYcOnw7Vlc319JCBlc3TDo28gYmVtIHByw7N4aW1vcyB1bnMgZG9zIG91dHJvcyBlIHN1Z2VyZW0gdW0gZ3J1cG8uCiAgICAqIE9zICRcY29sb3J7IzdDM0Y3Q317XHRleHR7MyBmaWxtZXMgZGUgYmFpeGFzIGJpbGhldGVyaWFzIGUgYmFpeGFzIGF2YWxpYcOnw7Vlc319JCBlc3TDo28gYmVtIGRpc3RhbnRlcyBkbyByZXN0byBkb3MgZmlsbWVzIGUgc3VnZXJlbSB1bSBncnVwby4KICAgICogT3MgJFxjb2xvcnsjMTZBMDg1fXtcdGV4dHs0IGZpbG1lcyBkZSBiYWl4YSBiaWxoZXRlcmlhIGUgYm9hcyBhdmFsaWHDp8O1ZXN9fSQgZXN0w6NvIGJlbSBwcsOzeGltb3MgdW5zIGRvcyBvdXRyb3MgZSBzdWdlcmVtIHVtIGdydXBvLgogICAgKiBPcyAkXGNvbG9ye2dyZWVufXtcdGV4dHsyIGZpbG1lcyBkZSBhbHTDrXNzaW1hIGJpbGhldGVyaWEgZSBiYWl4w61zc2ltYSBhdmFsaWHDp8Ojb319JCBlc3TDo28gYmVtIGRpc3RhbnRlcyBkbyByZXN0byBkb3MgZmlsbWVzIGUgc3VnZXJlbSB1bSBncnVwby4KICAgICogT3MgJFxjb2xvcnsjQ0Y1MzAwfXtcdGV4dHs2IGZpbG1lcyBjZW50cmFpcy9tZWRpYW5vcyBlbSB0ZXJtb3MgZGUgYmlsaGV0ZXJpYS9hdmFsaWHDp8Ojb319JCBlc3TDo28gYmVtIHByw7N4aW1vcyB1bnMgZG9zIG91dHJvcyBlIHN1Z2VyZW0gdW0gZ3J1cG8uCiAgICAKICAgIAoKYGBge3J9CmF0cmlidWljb2VzID0gZ2V0X2dydXBvcyhhZ3J1cGFtZW50b19oXzJkLCBudW1fZ3J1cG9zID0gMTo2KQoKYXRyaWJ1aWNvZXMgPSBhdHJpYnVpY29lcyAlPiUgCiAgICBmaWx0ZXIoayA9PSA1KSAlPiUKICAgIG11dGF0ZShmaWxtZSA9IGxhYmVsKSAlPiUgCiAgICBsZWZ0X2pvaW4oZmlsbWVzLCBieSA9ICJmaWxtZSIpCgpwIDwtIGF0cmlidWljb2VzICU+JQogICAgZ2dwbG90KGFlcyh4ID0gYXZhbGlhY2FvLAogICAgICAgICAgICAgICB5ID0gYmlsaGV0ZXJpYSwKICAgICAgICAgICAgICAgY29sb3VyID0gZ3J1cG8sCiAgICAgICAgICAgICAgIHRleHQgPSBwYXN0ZSgKICAgICAgICAgICAgICAgICAgICAiRmlsbWU6IiwgZmlsbWUsCiAgICAgICAgICAgICAgICAgICAgIlxuQmlsaGV0ZXJpYToiLCBiaWxoZXRlcmlhLCJtXG4iLAogICAgICAgICAgICAgICAgICAgICJBdmFsaWHDp8OjbzoiLCBhdmFsaWFjYW8pKSkgKyAKICAgIGdlb21faml0dGVyKHdpZHRoID0gLjAyLCBoZWlnaHQgPSAwLCBzaXplID0gMywgYWxwaGEgPSAuNikgKyAKICAgIGZhY2V0X3dyYXAofiBwYXN0ZShrLCAiIGdydXBvcyIpKSArIAogICAgc2NhbGVfY29sb3JfYnJld2VyKHBhbGV0dGUgPSAiRGFyazIiKSArCiAgICBzY2FsZV95X2xvZzEwKCkgKwogICAgbGFicyh5ID0gIkJpbGhldGVyaWEiLCB4ID0gIkF2YWxpYcOnw6NvIFJUIikKCgpnZ3Bsb3RseShwLCB0b29sdGlwID0gInRleHQiKSAlPiUKICAgIGxheW91dChhdXRvc2l6ZSA9IEYpCmBgYAoKPGJyPgoKKioqCgo8YnI+CgojIyMgUXVhaXMgb3Mgbm9tZXMgZG9zIGdydXBvcz8gCgo8YnI+CgokXGNvbG9yeyMxNkEwODV9e1x0ZXh0e0dydXBvIDEgKE9kZGJhbGwpOn19JCBGaWxtZXMgZW0gZ2VyYWwgX2JlbSByZWNlYmlkb3MgcGVsYSBjcsOtdGljYSBwb3LDqW0gbWFsIHJlY2ViaWRvcyBwZWxvIHDDumJsaWNvXywgbyBxdWUgc2UgcmVmbGV0ZSBubyBzZXUgYmFpeG8gYXJyZWNhZGFtZW50by4gTyBub21lIE9kZGJhbGwgcGFydGUgZG8gaW50ZXJlc2UgZGUgcGVzc29hcyBxdWUgc2UgY29uc2lkZXJhbSBleGPDqm50cmljYXMgZW0gYnVzY2FyZW0gZmlsbWVzIG5lc3NlIHBlcmZpbCBwYXJhIHJldmFsaWRhcmVtIG8gc2VudGltZW50byBkZSBleGNsdXNpdmlkYWRlLgoKPGJyLz4KCiRcY29sb3J7I0NGNTMwMH17XHRleHR7R3J1cG8gMiAoU2Vzc8OjbyBkYSBUYXJkZSk6fX0kIEZpbG1lcyBlbSBnZXJhbCBfbsOjbyB0w6NvIGJlbSByZWNlYmlkb3MgcGVsYSBjcsOtdGljYSBlIG1haXMgZm9ybXVsYWljb3NfLiBFbSB0ZXJtb3MgZGUgYmlsaGV0ZXJpYSBhIG1haW9yIHBhcnRlIGRlbGVzIGZvaSBiYWl4YSBtYXMgbyBmaWxtZSBzZSBwYWdvdS5PIG5vbWUgU2Vzc8OjIGRhIFRhcmRlIHBhcnRlIGRhIGlkZWlhIGRlIHF1ZSBmaWxtZXMgbWFpcyBmb3JtdWxhaWNvcyBlIGluZXhwcmVzc2l2b3MgZW0gdGVybW9zIGRlIGJpbGhldGVyaWEgY29tbyBvcyBkbyBncnVwbyBwb3ZvYXJlbSBlc3NlIGhvcsOhcmlvIGRhIHR2IGJyYXNpbGVpcmEuCgo8YnIvPgoKJFxjb2xvcnsjN0MzRjdDfXtcdGV4dHtHcnVwbyAzIChEZW1vbGl0aW9uIG9mIGEgYnVkZ2V0KTp9fSQgRmlsbWVzIGVtIGdlcmFsIF9tYWwgcmVjZWJpZG9zIHBlbGEgY3LDrXRpY2EgZSBwZWxvIHDDumJsaWNvXywgbyBxdWUgc2UgcmVmbGV0ZSBubyBzZXUgYmFpeG8gYXJyZWNhZGFtZW50byBlIGF2YWxpYcOnw7Vlcy4gTyBub21lIGRvIGdydXBvIHBhcnRlIGRvIGJheGlzc2ltbyByZW5kaW1lbnRvIGRvcyBmaWxtZXMgZW0gdGVybW9zIGZpbmFuY2Vpcm9zLCBhICJkZW1vbGnDp8OjbyIgZG8gZGluaGVpcm8gaW52ZXN0aWRvIG5hIHByb2R1w6fDo28gZG8gZmlsbWUuIAoKPGJyLz4KCiRcY29sb3J7bWFnZW50YX17XHRleHR7R3J1cG8gNCAoQnJva2UgUmVjb3JkcyBhbmQgQXdhcmRzKTp9fSQgRmlsbWVzIF9hY2xhbWFkb3MgcGVsYSBjcsOtdGljYV8gZSBkZSBmYXR1cmFtZW50byBkZWNlbnRlIG91IGRlICBzdWNlc3NvLCBvcyBmaWxtZXMgZGVzc2UgZ3J1cG8gc8OjbyBkZSB0b20gbWFpcyBzw6lyaW8gdHJhdGFuZG8gZGUgYXNzdW50b3Mgc2lnbmlmaWNhdGl2b3MgZSBnZXJhZG9yZXMgZGUgY29udHJvdsOpcnNpYSAoYXNzYXNzaW5hdG9zIGVtIHPDqXJpZSB2ZXLDrWRpY29zLCBuw6NvIGhldGVyb3NzZXh1YWxpZGFkZSwgdGVycm9yaXNtby4uICkuIE8gbm9tZSBkbyBncnVwbyDDqSB1bSB0cm9jYWRpbGhvIGNvbSBvIG5vbWUgZGUgdW0gZG9zIGZpbG1lcyBlIGEgcXVhbnRpZGFkZSBleG9yYml0YW50ZSBkZSBwcsOqbWlvcyBxdWUgZXNzZSBmaWxtZSBnYW5ob3UuIAoKPGJyLz4KCiRcY29sb3J7Z3JlZW59e1x0ZXh0e0dydXBvIDUgKEJsb2NrQnVzdGVycyk6fX0kIEZpbG1lcyBlbSBxdWUgSmFjayBhdHVvdSBxdWUgb3MgY3LDrXRpY29zIG7Do28gZ29zdGFyYW0gbMOhIG11aXRvIG1hcyBxdWUgZXhjZWRlcmFtIGVtIGJpbGhldGVyaWEsIGNvbSB1bWEgYXJyZWNhZGHDp8OjbyBnaXJhbmRvIG5hIGNhc2EgZGEgY2VudGVuYSBkZSBtaWxow7VlcyBkZSBkw7NsYXJlcy4gTyB0ZXJtbyBCbG9ja0J1c3RlciDDqSB1c3VhbG1lbnRlIGRhZG8gYSBmaWxtZXMgcXVlIGxvdGFtIGFzIHNhbGFzIGRlIGNpbmVtYSwgcXVlIMOpIG8gY2FzbyBkb3MgZmlsbWVzIHBlcnRlbmNlbnRlcyBhIGVzc2UgZ3J1cG8uCgo8YnI+CgoqKioKCjxici8+CgojIyMgRmlsbWUtZXhlbXBsbyBkZSBjYWRhIGdydXBvICAKCjxici8+CgokXGNvbG9yeyMxNkEwODV9e1x0ZXh0e0dydXBvIDEgKE9kZGJhbGwpOn19JAoKKiAqKlN0cm9uZ2VyKio6IEZpbG1lIGJpb2dyw6FmaWNvIHNvYnJlICdKZWZmIEJhdW1hbicsIHbDrXRpbWEgZG8gYXRlbnRhZG8gZGUgQm9zdG9uIHF1ZSBwZXJkZXUgYW1iYXMgYXMgcGVybmFzIG5hIGV4cGxvc8Ojby4gTyBmaWxtZSBmb2kgbXVpdG8gYmVtIHJlY2ViaWRvIHBlbG9zIGNyw610aWNvcyBxdWUgbyBlbG9naWFyYW0gcG9yIHNlciBiZW0gZXhlY3V0YWRvLCBjb21vdmVudGUgZSBwb3IgZm9jYXIgbnVtYSBoaXN0w7NyaWEgZGUgc3VwZXJhw6fDo28gYW8gaW52w6lzIGRlIHVzYXIgYSB0cmFnw6lkaWEgcGFyYSBhbGltZW50YXIgYSBwYXJhbsOzaWEgZW0gY2ltYSBkbyB0ZXJyb3Jpc21vLiBPIGZpbG1lIHBvcsOpbSBmb2kgdW0gZnJhY2Fzc28gZW0gdGVybW9zIGRlIGJpbGhldGVyaWEuCgo8YnIvPgoKJFxjb2xvcnsjQ0Y1MzAwfXtcdGV4dHtHcnVwbyAyIChTZXNzw6NvIGRhIFRhcmRlKTp9fSQKCiogKipMaWZlKio6IEZpbG1lIG5vIGfDqm5lcm8gZmljw6fDo28gY2llbnTDrWZpY2EgZXNwYWNpYWwsIHRldmUgdW0gYXJyZWNhZGFtZW50byBuw6NvIG11aXRvIGV4cHJlc3Npdm8KYXNzaW0gY29tbyBjcsOtdGljYXMgaWd1YWxtZW50ZSBwb3VjbyBlbnR1c2lhc21hZGFzLiBGb2kgY29uc2lkZXJhZG8gcG9yIG11aXRvcyBiZW0gZXhlY3V0YWRvcyBwb3LDqW0gcG91Y28gaW5vdmF0aXZvLgoKPGJyLz4KCiRcY29sb3J7IzdDM0Y3Q317XHRleHR7R3J1cG8gMyAoRGVtb2xpdGlvbiBvZiBhIGJ1ZGdldCk6fX0kIAoKKiAqKkRlbW9saXRpb24qKjogTmVzdGUgZmlsbWUgSmFrZSBhdHVhIG5vIHBhcGVsIGRlIHVtIGhvbWVtIHF1ZSB2b2x0YSBhbyB0cmFiYWxobyBkZXBvaXMgZGUgcGVyZGVyIGEgZXNwb3NhIGUgZW5jb250cmEgY29udGF0byBodW1hbm8gZW0gdW1hIGF0ZW5kZW50ZSBkZSB0ZWxlbWFya2V0aW5nIGFvIHJlY2xhbWFyIGRlIHVtYSB2ZW5kaW5nIG1hY2hpbmUuIE8gZmlsbWUgZm9pIHVtIGZyYWNhc3NvIGVtIHRlcm1vcyBkZSBhcnJlY2FkYW1lbnRvIGFzc2ltIGNvbW8gZW0gdGVybW9zIGRlIGNyw610aWNhLiBPIGZpbG1lIHRldmUgc2V1IHNjcmlwdCBhcG9udGFkbyBjb21vIGdyYW5kZSBwcm9ibGVtYSwgZXNzZSBmb2kgZGVzY3JpdG8gY29tbyAndGVudGFuZG8gYWZldGFyIHByb2Z1bmRpZGFkZScgZSBhbnRpLWNhcmlzbcOhdGljby4KICAgIAo8YnIvPgoKJFxjb2xvcnttYWdlbnRhfXtcdGV4dHtHcnVwbyA0IChCcm9rZSBSZWNvcmRzIGFuZCBBd2FyZHMpOn19JAoKKiAqKkJyb2tlYmFjayBNb3VudGFpbioqOiBQcm92YXZlbG1lbnRlIGEgbWVsaG9yIGF0dWHDp8OjbyBkZSBKYWtlIEd5bGxlbmhhYWwgYXTDqSBvIG1vbWVudG8sIGVzc2UgZmlsbWUgcmVuZGV1IGEgSmFrZSB1bWEgaW5kaWNhw6fDo28gYW8gT3NjYXIgZSBsZXZhbnRvdSBtdWl0YSBjb250cm92w6lyc2lhIHBvciBjb250ZXIgdW1hIGNlbmEgZGUgc2V4byBlbnRyZSBwZXNzb2FzIGRvIG1lc21vIHNleG8uIEEgQWNhZGVtaWEgKHJlc3BvbnPDoXZlbCBwb3IgZXNjb2xoZXIgb3MgdmVuY2Vkb3JlcyBkbyBPc2NhcikgZm9pIGFjdXNhZGEgZGUgaG9tb2ZvYmlhIHBvciBuw6NvIGVzY29saGVyIGVzc2UgZmlsbWUgY29tbyBvIGdhbmhhZG9yIGRlIE1lbGhvciBGb3RvZ3JhZmlhLCBhaW5kYSBhc3NpbSBCcm9rZWJhY2sgTW91bnRhaW4gZ2FuaG91IG91dHJvcyAxNDEgcHLDqm1pb3MgZSAxMjggbm9taW5hw6fDtWVzIGRlIGFjb3JkbyBjb20gbyBJTURCLiBPIGZpbG1lIGZvaSBjb25zaWRlcmFkbyB1bSBzdWNlc3NvIHRhbnRvIGVtIGZhdHVyYW1lbnRvIGNvbW8gZW0gYXZhbGlhw6fDo28uCgo8YnIvPgoKJFxjb2xvcntncmVlbn17XHRleHR7R3J1cG8gNSAoQmxvY2tCdXN0ZXJzKTp9fSQgCgoqICoqUHJpbmNlIG9mIFBlcnNpYTogVGhlIFNhbmRzIG9mIFRpbWUqKjogQmFzZWFkbyBubyBqb2dvIGRlIG1lc21vIG5vbWUsIGpvZ28gcXVlIGFpbmRhIMOpIHByYSBtdWl0b3MgdW1hIHJlZmVyw6puY2lhIGVtIHF1YWxpZGFkZSBlIGlub3Zhw6fDo28uIE8gZmlsbWUgcmVzdWx0b3UgZW0gY29tZW50w6FyaW9zIGRlY2VwY2lvbmFkb3MgdGFudG8gZGUgY3LDrXRpY29zIGUgZsOjcywgb3MgcXVhaXMgY3VyaW9zYW1lbnRlIG7Do28gZmFsaGFyYW0gZW0gY29udHJpYnVpciBwcm8gYXJyZWNhZGFtZW50byBkbyBmaWxtZS4KICAgIAo=